package com.car.loan.project.xr.service;

import com.car.loan.common.exception.loan.LoanParameterException;
import com.car.loan.common.utils.BeanUtils;
import com.car.loan.common.utils.SecurityUtils;
import com.car.loan.framework.web.domain.AjaxResult;
import com.car.loan.project.xr.domain.Customer;
import com.car.loan.project.xr.domain.Loan;
import com.car.loan.project.xr.domain.LoanCar;
import com.car.loan.project.xr.domain.LoanDetail;
import com.car.loan.project.xr.domain.LoanExt;
import com.car.loan.project.xr.domain.OverdueAdvancesLog;
import com.car.loan.project.xr.mapper.CustomerMapper;
import com.car.loan.project.xr.mapper.LoanCarMapper;
import com.car.loan.project.xr.mapper.LoanDetailMapper;
import com.car.loan.project.xr.mapper.LoanExtMapper;
import com.car.loan.project.xr.mapper.LoanMapper;
import com.car.loan.project.xr.mapper.OverdueAdvancesLogMapper;
import com.car.loan.project.xr.mapper.OverdueInfoMapper;
import com.car.loan.project.xr.service.impl.LoanServiceImpl;
import com.car.loan.project.xr.util.RedisDataUtil;
import com.car.loan.project.xr.util.bo.business.after.OverdueAdvancesBo;
import com.car.loan.project.xr.util.enums.after.AdvancesType;
import com.car.loan.project.xr.util.vo.LoanDetailVo.LoanBaseInfoVo;
import com.car.loan.project.xr.util.vo.after.OverdueAdvancesInfo;
import com.car.loan.project.xr.util.vo.after.OverdueUrgentLogInfo;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author huangding
 * @date 2020/2/26 22:14
 */
@Service
public class AdvancesService {

    @Resource
    private OverdueAdvancesLogMapper overdueAdvancesLogMapper;

    @Resource
    private LoanExtMapper loanExtMapper;

    @Autowired
    private LoanMapper loanMapper;

    @Autowired
    private LoanCarMapper loanCarMapper;

    @Autowired
    private LoanDetailMapper loanDetailMapper;

    @Autowired
    private RedisDataUtil redisDataUtil;

    @Autowired
    private LoanServiceImpl loanService;

    @Resource
    private OverdueInfoMapper overdueInfoMapper;

    @Resource
    private CustomerMapper customerMapper;

    public OverdueAdvancesInfo info(Long loanId) {
        OverdueAdvancesInfo overdueAdvancesInfo = new OverdueAdvancesInfo();

        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));

        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));

        Customer customer = customerMapper.selectById(loan.getCustomerId());

        overdueAdvancesInfo.setCustomerName(customer.getName());
        overdueAdvancesInfo.setIdCardNo(customer.getIdCardNo());
        overdueAdvancesInfo.setMobile(customer.getMobile());

        //基本信息
        LoanBaseInfoVo loanBaseInfoVo = loanService.getLoanBaseInfoVo(loan);
        loanBaseInfoVo.setFileNo(loanDetail.getFileNo());
        overdueAdvancesInfo.setLoanBaseInfo(loanBaseInfoVo);

        //业务信息
        OverdueUrgentLogInfo.BusinessInfo businessInfo = new OverdueUrgentLogInfo.BusinessInfo();
        BeanUtils.copyBeanProp(businessInfo, loanDetail);
        businessInfo.setBankName(redisDataUtil.getBankName(loan.getBankId()));
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setRate(loanExt.getRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        businessInfo.setTerm(loanExt.getTerm());
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setRate(loanExt.getRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        businessInfo.setTerm(loanExt.getTerm());
        overdueAdvancesInfo.setBusinessInfo(businessInfo);

        //车辆信息
        OverdueUrgentLogInfo.CarInfo carInfo = new OverdueUrgentLogInfo.CarInfo();
        BeanUtils.copyBeanProp(carInfo, loanCar);
        overdueAdvancesInfo.setCarInfo(carInfo);

        //逾期信息
        OverdueUrgentLogInfo.OverdueInfo overdueInfo = new OverdueUrgentLogInfo.OverdueInfo();
        overdueInfo.setOverdueAmount(loanExt.getOverdueAmount());
        overdueInfo.setAdvancesAmount(loanExt.getAdvancesAmount());
        overdueInfo.setOverdueMaxAmount(loanExt.getOverdueMaxAmount());
        overdueInfo.setOverdueTerm(loanExt.getOverdueTerm());
        overdueInfo.setOverdueCount(loanExt.getOverdueCount());
        Optional<com.car.loan.project.xr.domain.OverdueInfo> optionalOverdueInfo = overdueInfoMapper
            .selectOneByLoanIdAndItem(loanId, loanExt.getOverdueTerm());
        optionalOverdueInfo
            .ifPresent(info -> overdueInfo.setCurrentOverdueMaxAmount(info.getMaxOverdueAmount()));
        overdueAdvancesInfo.setOverdueInfo(overdueInfo);

        //垫款信息
        overdueAdvancesInfo.setAdvancesInfos(Lists.newArrayList());
        List<OverdueAdvancesLog> overdueAdvancesLogs = overdueAdvancesLogMapper
            .selectByLoanId(loanId);
        if (null != overdueAdvancesLogs && overdueAdvancesLogs.size() > 0) {
            List<OverdueAdvancesInfo.AdvancesInfo> advancesInfos = new ArrayList<>();
            overdueAdvancesLogs.forEach(overdueAdvancesLog -> {
                OverdueAdvancesInfo.AdvancesInfo advancesInfo = new OverdueAdvancesInfo.AdvancesInfo();
                advancesInfo.setDateTime(overdueAdvancesLog.getCreateTime());
                Integer type = overdueAdvancesLog.getType();
                if (AdvancesType.EXPENSES.type == type) {
                    advancesInfo.setExpensesAmount(overdueAdvancesLog.getAmount());
                } else if (AdvancesType.INCOME.type == type) {
                    advancesInfo.setIncomeAmount(overdueAdvancesLog.getAmount());
                }
                advancesInfo.setAdvancesBalance(overdueAdvancesLog.getBalance());
                advancesInfo.setRemark(overdueAdvancesLog.getRemark());
                advancesInfos.add(advancesInfo);
            });
            overdueAdvancesInfo.setAdvancesInfos(advancesInfos);
        }
        return overdueAdvancesInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    public synchronized AjaxResult input(OverdueAdvancesBo overdueAdvancesBo) {

        Optional<LoanExt> optionalLoanExt = loanExtMapper
            .selectByLoanId(overdueAdvancesBo.getLoanId());
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));

        BigDecimal advancesAmount = new BigDecimal(loanExt.getAdvancesAmount());

        BigDecimal amount = overdueAdvancesBo.getAmount();
        //每发生一次垫款，垫款余额=垫款余额-收入金额+支出金额
        Integer type = overdueAdvancesBo.getType();
        if (AdvancesType.EXPENSES.type == type) {
            advancesAmount = advancesAmount.add(amount, MathContext.DECIMAL128)
                .setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if (AdvancesType.INCOME.type == type) {
            advancesAmount = advancesAmount.subtract(amount, MathContext.DECIMAL128)
                .setScale(2, BigDecimal.ROUND_HALF_UP);
        } else {
            return AjaxResult.error("收支性质不对");
        }
        OverdueAdvancesLog overdueAdvancesLog = new OverdueAdvancesLog();
        overdueAdvancesLog.setBalance(advancesAmount.doubleValue());
        overdueAdvancesLog.setLoanId(overdueAdvancesBo.getLoanId());
        overdueAdvancesLog.setType(overdueAdvancesBo.getType());
        overdueAdvancesLog.setAmount(overdueAdvancesBo.getAmount());
        overdueAdvancesLog.setRemark(overdueAdvancesBo.getRemark());
        overdueAdvancesLog.setCreatorId(SecurityUtils.getLoginUserId());
        overdueAdvancesLog.setCreateTime(LocalDateTime.now());
        overdueAdvancesLogMapper.insert(overdueAdvancesLog);

        //更新垫款金额
        loanExt.setAdvancesAmount(advancesAmount.doubleValue());
        loanExtMapper.updateById(loanExt);

        return AjaxResult.success();
    }
}
